
package com.ktkj.init.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktkj.init.entity.Attachment;
import com.ktkj.init.exception.BusinessException;
import com.ktkj.init.mapper.AttachmentMapper;
import com.ktkj.init.service.AttachmentService;
import com.ktkj.init.utils.FileUtils;
import com.ktkj.init.utils.FtpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;


@Slf4j
@Service
public class AttachmentServiceImpl extends ServiceImpl<AttachmentMapper, Attachment> implements AttachmentService {

    @Value("${upload.file.path}")
    private String uploadFilePath;

    @Override
    public void downloadFile(String fileName, HttpServletResponse response) {
        //下载
        this.responseFileStream(fileName, response, "attachment");
    }

    @Override
    public void previewFile(String fileName, HttpServletResponse response) {
        //预览
        this.responseFileStream(fileName, response, "inline");
    }

    @Override
    public void responseFileStream(String fileName, HttpServletResponse response, String header) {
        String newFileName = fileName.substring(fileName.lastIndexOf(File.separator) + 1);
        InputStream is = null;
        ServletOutputStream outputStream = null;
        try {
            response.setHeader("Content-Disposition", header + ";filename=" + URLEncoder.encode(newFileName, "UTF-8"));
            InputStream inputStream = new FileInputStream(new File(fileName));
            is = inputStream;
            outputStream = response.getOutputStream();
            // 将文件写到输出流中
            FileCopyUtils.copy(is, outputStream);
        } catch (Exception ex) {
            log.error("responseFileStream.error|", ex);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                log.error("responseFileStream.error|", e);
            }
        }
    }

    @Override
    @Transactional
    public Attachment uploadFileLocalPath(MultipartFile file, String fileName, String modelName) {
        try {
            Attachment attachment = this.transferTo(file, fileName, modelName, "");
            saveOrUpdate(attachment);
            return attachment;
        } catch (Exception e) {
            log.error("uploadFileLocalPath.error", e);
            throw new BusinessException(-1, "文件上传失败");
        }
    }

    @Override
    @Transactional
    public Attachment uploadFileFtpPath(MultipartFile file, String fileName, String modelName) {
        String modelPath = FileUtils.getPath(modelName);
        try {
            Attachment attachment = this.transferTo(file, fileName, modelName, modelPath);
            InputStream inputStream = new FileInputStream(new File(uploadFilePath + attachment.getPath()));

            //上传至FTP服务器
            new Thread(() -> {
                FtpUtils ftpUtils = new FtpUtils();
                ftpUtils.uploadLocalFileFIS(modelPath, inputStream, fileName);
            }).start();

            //保存到数据库
            attachment.setPath(modelPath + fileName);
            saveOrUpdate(attachment);
            return attachment;
        } catch (Exception e) {
            log.error("uploadFileFtpPath.error", e);
            throw new BusinessException(-1, "文件上传失败");
        }
    }


    @Override
    public String downloadFileByFtp(String ftpFileName, String modelName) {
        FtpUtils ftpUtils = new FtpUtils();
        String ftpPath = ftpFileName.substring(1, ftpFileName.lastIndexOf(File.separator));
        String fileName = ftpFileName.substring(ftpFileName.lastIndexOf(File.separator) + 1);
        String savePath = FileUtils.getPath(uploadFilePath, modelName, true);
        ftpUtils.downloadFile(ftpPath, fileName, savePath);
        log.info("ftpPath={},fileName={},savePath={}", ftpPath, fileName, savePath);
        return savePath + fileName;
    }


    private Attachment transferTo(MultipartFile file, String fileName, String modelName, String modelPath) {
        Attachment attachment = null;
        try {
            if (StringUtils.isBlank(modelPath)) {
                modelPath = FileUtils.getPath(modelName);
            }
            String path = uploadFilePath + modelPath;
            FileUtils.mkdir(path);
            File fileNew = new File(path + fileName);
            file.transferTo(fileNew);
            attachment = new Attachment();
            attachment.setFileName(fileName);
            attachment.setPath(modelPath + fileName);
            attachment.setSize(fileNew.length());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return attachment;
    }
}
